package com.mrx.xbrowsersync.dao;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Repository;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.mrx.xbrowsersync.model.dto.BookmarkResponse;
import com.mrx.xbrowsersync.model.po.BookmarkPO;
import com.mrx.xbrowsersync.model.vo.BookmarkVO;

import lombok.SneakyThrows;

/**
 * @author Mr.X
 * @since 2024-03-05 下午 7:50:43
 */
@Repository
public class BookmarkMapper implements DisposableBean, InitializingBean {

    private static final Map<String, BookmarkPO> bookmarks = new ConcurrentHashMap<>();

    private static final Logger logger = LoggerFactory.getLogger(BookmarkMapper.class);

    private final Path BOOK_MARK_FILE = Path.of("./bookmarks.json");

    public BookmarkResponse initBookmarks(BookmarkVO vo) {
        logger.info("初始化书签: {}", vo);
        String id = UUID.randomUUID().toString();
        BookmarkPO newBookmark = BookmarkPO.of(id, null, LocalDateTime.now(), vo.getVersion());
        putAndSave(newBookmark);
        return BookmarkResponse.of(id, null, newBookmark.getLastUpdated(), newBookmark.getVersion());
    }

    public BookmarkPO getBookmarkById(String id) {
        logger.info("查询书签: {}", id);
        return bookmarks.get(id);
    }

    public BookmarkPO updateById(BookmarkPO po) {
        logger.info("更新书签: {}", po);
        String id = po.getId();
        po.setVersion(bookmarks.get(id).getVersion());
        return putAndSave(po);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        if (!BOOK_MARK_FILE.toFile().exists()) {
            logger.info("书签文件不存在, 跳过初始化数据");
            return;
        }
        JSONObject bookmarkJson = JSON.parseObject(Files.readString(BOOK_MARK_FILE));
        logger.info("启动系统, 初始化数据: {}", bookmarkJson);
        bookmarks.putAll(bookmarkJson.to(new TypeReference<>() {}));
    }

    @Override
    public void destroy() throws Exception {
        logger.info("关闭系统, 保存数据: {}", JSON.toJSONString(bookmarks));
        saveToFile();
    }

    @SneakyThrows
    private BookmarkPO putAndSave(BookmarkPO bookmark) {
        bookmarks.put(bookmark.getId(), bookmark);
        saveToFile();
        return bookmark;
    }

    private synchronized void saveToFile() throws IOException {
        Files.writeString(BOOK_MARK_FILE, JSON.toJSONString(bookmarks));
    }

}
